/** \file parserHelper.c
* Implementation file for helper functions of gminiParser.c
*/
#include "parserHelper.h"

TypeList temp_type;
GminiGraph parsingGraph;

#ifdef DEBUG
void print(const TypeList & l)
{
	for (int i=0;i<l.size();i++)
		cout<< (int)(l[i])<< " ";
}
void printVariables()
{

	cout<<"---------------\n";
	VariableMap::iterator it;
	for ( it=parsingGraph.variables.begin() ; it != parsingGraph.variables.end(); it++ )
	{
	    cout <<"["<< ((*it).first) <<
	    	 "]=> ";
	    print((*it).second);
	    cout<<endl;
	}
	cout<<"-------<>------\n";

}
#else
#define print(a)
#define printVariables()
#endif	

bool checkBasicVariable (ANTLR3_COMMON_TOKEN_struct* a, Type t)
{
	string varName = (string)((char*)a->getText(a)->chars);
	VariableMap::iterator it=parsingGraph.variables.find(varName);
	if (it==parsingGraph.variables.end())
	{
	 	string s = "Variable " + varName + " is Not Defined";
	 	errorMessage(a, s);
	 	return false;
	 	
	}
	else if ((it->second)[0]!=t)
	{
		//out((int)(it->second)[0]);
		string s1 = "Incompatible Type with " + varName;
		errorMessage(a,s1);
		return false;
		//cout<< "Incompatible type for "<<varName<< "!\n";
	}
	return true;
}
Type getBasicType (string varName, int index)
{
	out("{checking <"<<varName<<index<<">");//assuming index is one digit
	VariableMap::iterator it=parsingGraph.variables.find(varName);
	if (it==parsingGraph.variables.end() || index+1>(it->second).size())
	{
		out("check returning "<<(int)t_NOT_DEFINED<<"}");
		return t_NOT_DEFINED;
	}
	out("check returning "<<(int)(it->second)[index]<<"}");
	return((it->second)[index]);
}
TypeList getCompositeType (string varName)
{
	out("{checking <"<<varName<<">");//assuming index is one digit
	VariableMap::iterator it=parsingGraph.variables.find(varName);
	if (it==parsingGraph.variables.end())
	{
		out("check returning empty list}");
		return TypeList();
	}
	out("check returning ");
	print(it->second);
	out("}");
	return(it->second);
}
void appendType(Type t)
{
	temp_type.push_back(t);
}
void storeVariable(string varName)
{
	parsingGraph.variables[varName]=temp_type;
	out("->"<<varName);
	printVariables();
	temp_type.clear();
}

bool checkPairIndex(ANTLR3_COMMON_TOKEN_struct* a,string index) 
{
	if (index!="1" && index!="2")
	{	//cout <<"Pair index ("<<index<<") out of bound! Only 1, 2 indices are valid.\n";
		string message = "Pair Index {" + index + "} is out of Bound - Valid Rand {1,2}";
		errorMessage(a,message);
		return false;
	}
	return true;
		 
}
TypeList appendLists(TypeList c,TypeList d)
{
	out("{arguments of append");
	print(c);
	print(d);
	for (int i=0;i<d.size();i++)
		c.push_back(d[i]);
	out("output after appending");
	print(c);
	out("}");
	return c;
}
TypeList getRemainingType(const TypeList & originalList, int index, int & finished) //if array index=1 always, if pair can be 1 or 2
{
	out("original List:");
	print(originalList);
	out("Type="<<(int)originalList[index]<< " Index="<<index);
	if (originalList[index]==t_BOOL || originalList[index]==t_INT)
	{
		finished=index;
		TypeList l;
		l.push_back(originalList[index]);
		return l;
	}
	else if (originalList[index]==t_PAIR)
	{
		int next_finished;
		TypeList l;
		l.push_back(originalList[index]);
		TypeList l1=getRemainingType(originalList,index+1,next_finished);
		TypeList l2=getRemainingType(originalList,next_finished+1,next_finished);
		l=appendLists(l,appendLists(l1,l2));
		finished=next_finished;
		out("print L:");
		print(l);
		return l;
	}
	else if (originalList[index]==t_ARRAY)
	{
		int next_finished;
		TypeList l;
		l.push_back(originalList[index]);
		l=appendLists(l,getRemainingType(originalList,index+1,next_finished));
		finished=next_finished;
		out("print L:");
		print(l);
		return l;
	}
	else
	{
		out("ERROR");
		return TypeList();
	}		
}

TypeList getRemainingType(string varName, int index) //if array index=1 always, if pair can be 1 or 2
{
	out("{Remaining type <"<<varName<<index<<">");//assuming index is one digit
	VariableMap::iterator it=parsingGraph.variables.find(varName);
	if (it==parsingGraph.variables.end() || index+1>(it->second).size())
	{
		out("remaining Type returning empty list}");
		return TypeList();
	}

	if (index!=1 && index!=2)
	{
		out("remaining Type returning empty list ");
		return(TypeList());
	}

	int f;
	if (index==2)
	{
		getRemainingType((it->second),1,index);
		index++;
	}
	if (index+1>(it->second).size())
	{
		out("remaining Type returning empty list}");
		return TypeList();
	}

	TypeList list= getRemainingType((it->second),index,f);
	out("remaining Type returning ");
	print(list);
	out("}");
	return(list);
}
